<?php
/**
 * function.php 实用函数集
 * 该文件中包含一些实用的函数集，供其他的页面调用。
 */
require_once 'setting.php';

require_once INCLUDESPATH . 'db/User.php';
require_once INCLUDESPATH . 'db/UserDAO.php';
require_once INCLUDESPATH . 'db/Word.php';
require_once INCLUDESPATH . 'db/WordDAO.php';

require_once INCLUDESPATH . 'dict/IcibaDict.php';
require_once INCLUDESPATH . 'dict/DictcnDict.php';

# start the session function
if (!isset($_SESSION)) {
	session_start();
}

function isLogined() {
	if (isset($_SESSION['user'])) {
		return true;
	} else {
		return false;
	}
}

function isRememberMe() {
	if (isset($_COOKIE['username'], $_COOKIE['password'])) {
		$userdao = new UserDAO();
		$users = $userdao->retrieveByProperty("username", $_COOKIE['username']);
		if (empty($users)) {
			return false;
		} else {
			$user = $users[0];
			if ($_COOKIE['password'] == $user->getPassword()) {
				$_SESSION['user'] = $user;
				$_SESSION['username'] = $user->getUsername();
				return true;
			} else {
				return false;
			}
		}
	} else {
		return false;
	}
}

function getCurrentUserId() {
	if (isLogined()) {
		return $_SESSION['user']->getId();
	} else {
		return -1;
	}
}

function validUsername($username) {
	$rawUsername = $username;
	$username = stripAllTags($username);
	$username = removeAccents($username);
	// kill octets
	$username = preg_replace( '|%([a-fA-F0-9][a-fA-F0-9])|', '', $username );
	// kill entities
	$username = preg_replace( '/&.+?;/', '', $username );
	// Consolidate contiguous whitespace
	$username = preg_replace( '|\s+|', ' ', $username );

	if ($rawUsername === $username) {
		return true;
	} else {
		return false;
	}
}

function userExist($username) {
	$user = usernameExists($username) ? usernameExists($username) : emailExists($username);
	if ($user === false) {
		return false;
	} else {
		return $user;
	}
}

/**
 * 判断当前用户是否已经存储该单词
 * 
 * @param $word
 */
function wordExist($userid, $word) {
	$worddao = new WordDAO();
	$properties = array (
					'userid' => $userid,
					'key'    => $word);
	$words = $worddao->retrieveByProperties($properties);
	if (empty($words)) {
		return false;
	} else {
		return $words[0];
	}
}

/**
 * 判断当前用户是否拥有当前ID的单词
 * 
 * @param $word
 */
function wordExistWithId($userid, $id) {
	$worddao = new WordDAO();
	$properties = array (
					'userid' => $userid,
					'id'    => $id);
	$words = $worddao->retrieveByProperties($properties);
	if (empty($words)) {
		return false;
	} else {
		return $words[0];
	}
}

/**
 * Checks whether the given username exists.
 *
 * @author hutushen222 2010-08-11
 *
 * @param string $username -- an username
 * @return User | bool -- user object on success and false on failure.
 */
function usernameExists($username) {
	$userdao = new UserDAO();
	$users = $userdao->retrieveByProperty("username", $username);
	if (!empty($users)) {
		return $users[0];
	} else {
		return false;
	}
}

/**
 * Verifies that an email is valid.(change from wordpress)
 *
 * @author hutushen222 2010-08-11
 *
 * @param string $email -- Email address to verify.
 * @return bool -- true on valid and false on invalid
 */
function validEmail( $email) {
	// Test for the minimum length the email can be
	if ( strlen( $email ) < 3 ) {
		return false;
	}
	// Test for an @ character after the first position
	if ( strpos( $email, '@', 1 ) === false ) {
		return false;
	}

	// Split out the local and domain parts
	list( $local, $domain ) = explode( '@', $email, 2 );

	// LOCAL PART
	// Test for invalid characters
	if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) {
		return false;
	}

	// DOMAIN PART
	// Test for sequences of periods
	if ( preg_match( '/\.{2,}/', $domain ) ) {
		return false;
	}

	// Test for leading and trailing periods and whitespace
	if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) {
		return false;
	}

	// Split the domain into subs
	$subs = explode( '.', $domain );

	// Assume the domain will have at least two subs
	if ( 2 > count( $subs ) ) {
		return false;
	}

	// Loop through each sub
	foreach ( $subs as $sub ) {
		// Test for leading and trailing hyphens and whitespace
		if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) {
			return false;
		}

		// Test for invalid characters
		if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) {
			return false;
		}
	}

	// Congratulations your email made it!
	return true;
}

/**
 * Checks whether the given email exists.
 *
 * @author hutushen222 2010-08-11
 *
 * @param string $email -- an email
 * @return User | bool -- user object on success and false on failure.
 */
function emailExists($email) {
	$userdao = new UserDAO();
	$users = $userdao->retrieveByProperty("email", $email);
	if (!empty($users)) {
		return $users[0];
	} else {
		return false;
	}
}

/**
 * @todo 检验密码是否符合规范，主要是密码的长度等
 *
 * @param $password
 */
function validPassword($password) {
	return true;
}

function validPasswords($password, $repassword) {
	if ($password === $repassword) {
		return true;
	}
	return false;
}

/**
 * @todo validate question, 主要是当用户输入时的验证
 *
 * @param unknown_type $question
 */
function validQuestion($question) {
	return true;
}

/**
 * @todo 验证用户的安全问题的回答的格式
 *
 * @param $answer
 */
function validAnswer($answer) {
	return true;
}

/**
 * @todo 检测验证码是否满足规则，由字母和数字组成的序列，其他的都不符合
 *
 * @param $captcha
 */
function validCAPTCHA($captcha) {

	return true;
}

/**
 * @todo validate word, only with letters and space
 *
 * @param $word
 */
function validWord($word) {
	return true;
}

/**
 * @todo 如果当前的路径属于几个指定的路径中的一个，则合法
 * 
 * @param $path
 */
function validRedirectPath($path) {
	return true;
}


/**
 * Properly strip all HTML tags including script and style.(change from wordpress)
 *
 * @author hutushen222 2010-08-11
 *
 * @param string $string -- String containing HTML tags
 * @param bool $removeBreaks -- optional Whether to remove left over line breaks and white space chars
 * @return string -- The processed string.
 */
function stripAllTags($string, $removeBreaks = false) {
	$string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string );
	$string = strip_tags($string);

	if ( $removeBreaks ) {
		$string = preg_replace('/[\r\n\t ]+/', ' ', $string);
	}

	return trim($string);
}

/**
 * Converts all accent characters to ASCII characters.(change from wordpress)
 *
 * If there are no accent characters, then the string given is just returned.
 *
 * @author hutushen222 2010-08-11
 *
 * @param string $string -- Text that might have accent characters
 * @return string -- Filtered string with replaced "nice" characters.
 */
function removeAccents($string) {
	if ( !preg_match('/[\x80-\xff]/', $string) )
	return $string;

	if (seems_utf8($string)) {
		$chars = array(
		// Decompositions for Latin-1 Supplement
		chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
		chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
		chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
		chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
		chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
		chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
		chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
		chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
		chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
		chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
		chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
		chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
		chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
		chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
		chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
		chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
		chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
		chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
		chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
		chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
		chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
		chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
		chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
		chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
		chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
		chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
		chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
		chr(195).chr(191) => 'y',
		// Decompositions for Latin Extended-A
		chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
		chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
		chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
		chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
		chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
		chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
		chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
		chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
		chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
		chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
		chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
		chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
		chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
		chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
		chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
		chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
		chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
		chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
		chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
		chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
		chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
		chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
		chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
		chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
		chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
		chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
		chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
		chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
		chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
		chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
		chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
		chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
		chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
		chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
		chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
		chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
		chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
		chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
		chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
		chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
		chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
		chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
		chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
		chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
		chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
		chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
		chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
		chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
		chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
		chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
		chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
		chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
		chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
		chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
		chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
		chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
		chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
		chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
		chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
		chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
		chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
		chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
		chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
		chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
		// Euro Sign
		chr(226).chr(130).chr(172) => 'E',
		// GBP (Pound) Sign
		chr(194).chr(163) => '');

		$string = strtr($string, $chars);
	} else {
		// Assume ISO-8859-1 if not UTF-8
		$chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
		.chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
		.chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
		.chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
		.chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
		.chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
		.chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
		.chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
		.chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
		.chr(252).chr(253).chr(255);

		$chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";

		$string = strtr($string, $chars['in'], $chars['out']);
		$double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
		$double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
		$string = str_replace($double_chars['in'], $double_chars['out'], $string);
	}

	return $string;
}

/**
 * Jump to a given page
 *
 * @param unknown_type $url
 */
function jumpToPage($url) {
	header('Location: ' . $url);
}

/**
 * 搜索单词的释义
 *
 * @param $word
 */
function lookup($word) {
	$results = array();

	# 取得Iciba的对应释义
	$iciba = new IcibaDict();
	# 从词典中获得释义结果的数组
	$result = $iciba->lookup($word);
	# 将结果变换为Word对象
	$result = initWord($result);
	if (!is_null($result)) {
		$results['iciba'] = $result;
	}

	# 取得DictCN的对应的释义
	$dictcn = new DictcnDict();
	# 从词典中获得释义结果的数组
	$result = $dictcn->lookup($word);
	# 将结果变换为Word对象
	$result = initWord($result);
	if (!is_null($result)) {
		$results['dictcn'] = $result;
	}
	
	# @todo 其他的词典

	return $results;
}

/**
 * 初始化一个返回的单词的释义
 *
 * @param $result
 */
function initWord($result) {
	if ($result == NULL || empty($result)) {
		return null;
	}
	$word = new Word();
	$word->setKey($result['key']);
	$word->setPS($result['ps']);
	$word->setPron($result['pron']);
	$acceptation = "";
	foreach ($result['pos'] as $pos) {
		$acceptation .= $pos;
	}
	$word->setAcceptation($acceptation);
	return $word;
}

/**
 * return a formated string date with format "0000-00-00".
 *
 * @param int $time
 * @author hutushen222
 * @return string date -- format 0000-00-00
 */
function formatdate($time) {
	return date("Y-m-d", $time);
}

/**
 * return a formated string time with format "0000-00-00 00:00:00"
 *
 * @param int $time
 * @author hutushen222
 * @return string time -- format 0000-00-00 00:00:00
 */
function formattime($time) {
	return date("Y-m-d H:i:s u", $time);
}

function testToDie($objects, $desc = '') {
	echo '<dl>';
	foreach ($objects as $key => $value) {
		echo '<dt>' . $key . '</dt>';
		echo '<dd>';
		echo '<pre>';
		echo var_dump($value);
		echo '</pre>';
		echo '</dd>';
	}
	echo '</dl>';
	die($desc);
}
?>